package com.sg.service.biz.component.nb;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sg.common.exception.BizException;
import com.sg.common.util.CommonFunctionHelper;
import com.sg.dto.biz.component.common.GetListIntelligentAnswersDto;
import com.sg.dto.biz.component.req.*;
import com.sg.dto.biz.component.res.*;
import okhttp3.*;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author ： 手工接入方法
 * @version 1.0
 * @since 2022/5/28 15:32
 */
@Service
public class NbIntelligentCommunication {


    @Trace(operationName = "M2执行三方文件上传接口（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public String uploadFileToOpenAI(ImplementResourceFileToThirdPartyReqDto reqDto) throws Exception {
        OkHttpClient client = new OkHttpClient();
        File file = CommonFunctionHelper.getBaseInfoFromLocal().getLocalFile().get(reqDto.getResourceFileRelaPath());
        // 创建请求体，包含文件和表单字段
        MultipartBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(),
                        RequestBody.create(MediaType.parse("application/octet-stream"), file))
                .addFormDataPart("purpose", "file-extract")
                .build();

        // 构建请求
        Request request = new Request.Builder()
                .url(reqDto.getIntelliQaAddress() + "/files")
                .post(requestBody)
                .addHeader("Authorization", "Bearer " + reqDto.getKey())
                .build();

        // 发送请求并获取响应
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new Exception("Unexpected code " + response);

            // 解析响应JSON以获取文件ID
            String responseString = response.body().string();
            JSONObject jsonResponse = JSONObject.parseObject(responseString);
            return jsonResponse.getString("id");
        }

    }

    private String qPlusAcquireContent(String jsonStr) {
        String retContent = "";
        JSONObject rootObject = JSON.parseObject(jsonStr);

        // 解析choices数组
        JSONArray choicesArray = rootObject.getJSONArray("choices");
        for (int i = 0; i < choicesArray.size(); i++) {
            JSONObject choiceObject = choicesArray.getJSONObject(i);
            JSONObject messageObject = choiceObject.getJSONObject("message");
            String role = messageObject.getString("role");
            String content = messageObject.getString("content");
            System.out.println("Role: " + role);
            System.out.println("Content: " + content);
            retContent = retContent + content;
        }
        return retContent;
    }

    /**
     * code:implementThirdPartIntelligentQaInterface
     * name:M2执行第三方智能问答接口
     * desc:undefined
     * gen by moon at 12/10/2023, 3:20:08 AM
     **/
    @Trace(operationName = "M2执行第三方智能问答接口")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementThirdPartIntelligentQaInterfaceRespDto implementThirdPartIntelligentQaInterface(ImplementThirdPartIntelligentQaInterfaceReqDto reqDto) {
        ImplementThirdPartIntelligentQaInterfaceRespDto retData = new ImplementThirdPartIntelligentQaInterfaceRespDto();
        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(10000, TimeUnit.SECONDS)
                .readTimeout(10000, TimeUnit.SECONDS)
                .build();

        String chatAddress = reqDto.getIntelliQaAddress();
        JSONObject reqJson = new JSONObject();
        reqJson.put("model", reqDto.getModelVersion());
        List<Map<String, Object>> messages = new ArrayList<>();
        for (GetListIntelligentAnswersDto one : reqDto.getGetListIntelligentAnswersList()) {
            Map<String, Object> elm = new HashMap<>();
            if (reqDto.getModelVersion().equals("qwen-plus")
                    && one.getRole() != null
                    && !one.getRole().equals("user")
                    && !one.getRole().equals("assistant")) {
                one.setRole("assistant");
            }
            elm.put("role", one.getRole());
            elm.put("content", one.getContent());
            messages.add(elm);
        }
        if (reqDto.getModelVersion().equals("qwen-plus")) {
            Map<String, Object> qwenMes = new HashMap<>();
            reqJson.put("messages", messages);
//             reqJson.put("input",qwenMes);
            chatAddress = chatAddress + "/chat/completions";
        } else if (reqDto.getModelVersion().startsWith("gpt")) {
            reqJson.put("messages", messages);
        } else if (reqDto.getModelVersion().startsWith("qwen-long")) {
            reqJson.put("stream", true);
            reqJson.put("messages", messages);
            Map<String, Boolean> streamOptions = new HashMap<>();
            streamOptions.put("include_usage", false);
            reqJson.put("stream_options", streamOptions);
            chatAddress = chatAddress + "/chat/completions";
        }


        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        RequestBody body = RequestBody.create(JSON, reqJson.toJSONString());

        Request request = new Request.Builder()
                .url(chatAddress)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + reqDto.getKey())  // 替换为你的API密钥
                .post(body)
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

            String responseBody = response.body().string();
            System.out.println(responseBody);
            retData.setContent(responseBody);
            if (reqDto.getModelVersion().equals("qwen-plus")) {
                JSONObject retJson = JSONObject.parseObject(responseBody);
                String extractedText = qPlusAcquireContent(retJson.toJSONString());
                retData.setRole("assistant");
                retData.setContent(extractedText);
            } else if (reqDto.getModelVersion().startsWith("gpt")) {
                // 输出响应内容
                JSONObject retJson = JSONObject.parseObject(responseBody);
                JSONArray choicesJsonArray = retJson.getJSONArray("choices");
                Map<String, Object> captureContent = new HashMap<>();
                for (int i = 0; i < choicesJsonArray.size(); i++) {
                    JSONObject choiceJson = choicesJsonArray.getJSONObject(i);
                    JSONObject messageJson = choiceJson.getJSONObject("message");
                    retData.setRole(messageJson.getString("role"));
                    retData.setContent(messageJson.getString("content"));
                    break;
                }
            } else if (reqDto.getModelVersion().startsWith("qwen-long")) {
                // 输出响应内容
                String longMsg = assembleResponse(responseBody);
                String dealLongMsg = longMsg.replaceAll("\"", "");
                retData.setContent(dealLongMsg);
            }


        } catch (Exception e) {
            throw new BizException("-1", e.getMessage(), false);
        }
        return retData;
    }

    private static String assembleResponse(String responseString) {
        // 将响应字符串按行分割
        String[] chunks = responseString.split("\n");
        StringBuilder fullResponse = new StringBuilder();

        for (String chunk : chunks) {
            System.out.println(chunk);
            if (chunk.contains("[DONE]")) {
                continue;
            }
            if (chunk.startsWith("data:")) {
                // 提取data后面的JSON字符串
                String json = chunk.substring(5).trim();
                // 解析JSON字符串，提取content字段
                // 这里使用简化的字符串操作，实际应用中应使用JSON解析库
                int startIndex = json.indexOf("\"content\":\"") + 10;
                int endIndex = json.indexOf("\"", startIndex + 1);
                String content = json.substring(startIndex, endIndex);
                fullResponse.append(content);
            }
        }

        return fullResponse.toString();
    }

    public static void main(String[] args) {
        NbIntelligentCommunication o = new NbIntelligentCommunication();
        ImplementManuallyParsingInstructionParametersReqDto req = new ImplementManuallyParsingInstructionParametersReqDto();
        req.setContent("【指令模板6】 { \"customField\": \"记录想法\", \"customField1\": \"晚上去吃烤鱼\" }");
        o.implementManuallyParsingInstructionParameters(req);
//        NbIntelligentCommunication o = new NbIntelligentCommunication();
//        ImplementThirdPartIntelligentQaInterfaceReqDto req = new ImplementThirdPartIntelligentQaInterfaceReqDto();
//        req.setIntelliQaAddress("https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation");
//        req.setKey("sk-df6b93e207734ba7aaccebccf7c2ceac");
//        req.setModelVersion("qwen-plus");
//
//
//        GetListIntelligentAnswersDto reqElm1  = new GetListIntelligentAnswersDto();
//        reqElm1.setRole("user");
//        reqElm1.setContent("我想知道用户体验五要素中的结构层是什么意思，\n");
//        req.getGetListIntelligentAnswersList().add(reqElm1);
//
//        GetListIntelligentAnswersDto reqElm2  = new GetListIntelligentAnswersDto();
//        reqElm2.setRole("system");
//        reqElm2.setContent("用户体验五要素是由Jesse James Garrett提出的，包括战略层、范围层、结构层、框架层和表现层五个层次。其中，结构层是中间的第二层，主要关注的是信息架构和交互设计。 结构层主要包括两大部分： 1. 信息架构（Information Architecture）：这是指对网站或应用的内容和功能进行组织和分类，创建逻辑且易于导航的体系结构。这涉及到如何将内容划分为各个部分、类别和子类别，并通过标签、菜单、链接等方式让用户能够方便地找到所需的信息。 2. 交互设计（Interaction Design）：交互设计关注用户与产品之间的交流过程，包括定义用户行为、设定反馈机制以及设计操作流程等。它的目标是确保用户在使用产品的过程中，可以自然流畅地完成任务，同时获得良好的体验。 总的来说，结构层的任务就是为用户提供一个清晰、合理且高效的交互框架，使他们能够在满足其需求的同时，享受到便捷、愉悦的使用过程。\n");
//        req.getGetListIntelligentAnswersList().add(reqElm2);
//
//        GetListIntelligentAnswersDto reqElm3  = new GetListIntelligentAnswersDto();
//        reqElm3.setRole("user");
//        reqElm3.setContent("我想知道用户体验五要素当中关于战略层与结构层之间的关系是什么\n");
//        req.getGetListIntelligentAnswersList().add(reqElm3);
//
//        o.implementThirdPartIntelligentQaInterface(req);
    }

    /**
     * code:manuallyParsingInstructionParameters
     * name:M2执行人工解析指令参数
     * desc:undefined
     * gen by moon at 12/10/2023, 1:25:06 PM
     **/
    @Trace(operationName = "M2执行人工解析指令参数")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementManuallyParsingInstructionParametersRespDto implementManuallyParsingInstructionParameters(ImplementManuallyParsingInstructionParametersReqDto reqDto) {
        ImplementManuallyParsingInstructionParametersRespDto retData = new ImplementManuallyParsingInstructionParametersRespDto();
        //Pattern pattern = Pattern.compile("\\{[^}]*\\}");
        Pattern pattern = Pattern.compile("\\{(?:[^{}]*|\\{(?:[^{}]*|\\{[^{}]*\\})*\\})*\\}");
        Matcher matcher = pattern.matcher(reqDto.getContent());

        String targetStr = null;
        while (matcher.find()) {
            targetStr = matcher.group();
            break;
        }
        if (targetStr == null) {
            return retData;
        }
        JSONObject jo = JSONObject.parseObject(targetStr);
        retData.setCustomField(jo.getString("customField"));
        retData.setCustomField1(jo.getString("customField1"));
        retData.setCustomField2(jo.getString("customField2"));
        retData.setCustomField3(jo.getString("customField3"));
        retData.setCustomField4(jo.getString("customField4"));
        retData.setCustomField5(jo.getString("customField5"));
        retData.setCustomField6(jo.getString("customField6"));
        retData.setCustomField7(jo.getString("customField7"));
        retData.setCustomField8(jo.getString("customField8"));
        if (retData.getCustomField() != null && retData.getCustomField().equals("了解重要工作提醒")) {
            retData.setCustomField("IMPORT_WORK_REMIND");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("想问答")) {
            retData.setCustomField("QUESTION_ANSWER");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("智能服务专业工作")) {
            retData.setCustomField("INTELLIGENT_SERVICE");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("提出问题")) {
            retData.setCustomField("RAISE_QUESTION");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("安排任务")) {
            retData.setCustomField("ASSIGN_TASK");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("记录创意想法")) {
            retData.setCustomField("RECORD_IDEAS");
        } else if (retData.getCustomField() != null && retData.getCustomField().equals("记录重要笔记")) {
            retData.setCustomField("RECORD_MESSAGE");
        } else {
            retData.setCustomField("NO_MATCH_COMMAND");
        }

        String cmd = jo.getString("指令名称");
        if (cmd != null && cmd.equals("了解重要工作提醒")) {
            retData.setCustomField("IMPORT_WORK_REMIND");
        } else if (cmd != null && cmd.equals("想问答")) {
            retData.setCustomField("QUESTION_ANSWER");
            retData.setCustomField1(jo.getString("提问内容"));
        } else if (cmd != null && cmd.equals("智能服务专业工作")) {
            retData.setCustomField("INTELLIGENT_SERVICE");
            retData.setCustomField1(jo.getString("想知道内容"));
        } else if (cmd != null && cmd.equals("提出问题")) {
            retData.setCustomField("RAISE_QUESTION");
            retData.setCustomField1(jo.getString("问题名称"));
            retData.setCustomField2(jo.getString("发起人"));
            retData.setCustomField3(jo.getString("负责人"));
            retData.setCustomField4(jo.getString("问题等级"));
            retData.setCustomField5(jo.getString("问题总结"));
        } else if (cmd != null && cmd.equals("安排任务")) {
            retData.setCustomField("ASSIGN_TASK");
            retData.setCustomField1(jo.getString("任务名称"));
            retData.setCustomField2(jo.getString("安排人"));
            retData.setCustomField3(jo.getString("负责人"));
            retData.setCustomField4(jo.getString("截止时间"));
            retData.setCustomField5(jo.getString("任务总结"));
        } else if (cmd != null && cmd.equals("记录创意想法")) {
            retData.setCustomField("RECORD_IDEAS");
            retData.setCustomField1(jo.getString("想法内容"));
        } else if (cmd != null && cmd.equals("记录重要笔记")) {
            retData.setCustomField("RECORD_MESSAGE");
            retData.setCustomField1(jo.getString("笔记内容"));
        }
        return retData;
    }

    /**
     * code:receptionService
     * name:M2约定记录创意想法入参
     * desc:undefined
     * gen by moon at 1/23/2024, 2:13:36 AM
     **/
    @Trace(operationName = "M2约定记录创意想法入参")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementSmartSessionReceiveFieldInputRespDto implementSmartSessionReceiveFieldInput(ImplementSmartSessionReceiveFieldInputReqDto reqDto) {
        return BeanUtil.toBean(reqDto, ImplementSmartSessionReceiveFieldInputRespDto.class);
    }

    /**
     * code:receptionService
     * name:M2约定字段：通义千问模型版本、chatGpt模型版本
     * desc:undefined
     * gen by moon at 12/13/2024, 10:42:33 PM
     **/
    @Trace(operationName = "M2约定字段：通义千问模型版本、chatGpt模型版本")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public QueryFileQaDetailRespDto queryFileQaDetail(QueryFileQaDetailReqDto reqDto) {
        return BeanUtil.toBean(reqDto, QueryFileQaDetailRespDto.class);
    }

    /**
     * code:thirtPartFileUpload
     * name:M2执行三方文件上传接口（特殊方法）
     * desc:undefined
     * gen by moon at 12/13/2024, 10:42:45 PM
     **/
    @Trace(operationName = "M2执行三方文件上传接口（特殊方法）")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public ImplementResourceFileToThirdPartyRespDto implementResourceFileToThirdParty(ImplementResourceFileToThirdPartyReqDto reqDto) {
        ImplementResourceFileToThirdPartyRespDto retData = new ImplementResourceFileToThirdPartyRespDto();
        try {
            String fileId = uploadFileToOpenAI(reqDto);
            retData.setThirtPartFileId(fileId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retData;
    }

    /**
     * code:receptionService
     * name:M2接收出参
     * desc:undefined
     * gen by moon at 12/13/2024, 10:43:01 PM
     **/
    @Trace(operationName = "M2接收出参")
    @Tags({@Tag(key = "参数", value = "arg[0]"),
            @Tag(key = "返回值", value = "returnedObj")})
    public AddObjectStorageConfigRespDto addObjectStorageConfig(AddObjectStorageConfigReqDto reqDto) {
        return BeanUtil.toBean(reqDto, AddObjectStorageConfigRespDto.class);
    }
    //手工接入方法
}
